package com.dailyblue.java.project.oa.commons.filter;

import com.alibaba.fastjson.JSONArray;
import com.dailyblue.java.project.oa.commons.bean.Emp;
import com.dailyblue.java.project.oa.commons.bean.EmpDetails;
import com.dailyblue.java.project.oa.commons.config.JwtConfig;
import com.dailyblue.java.project.oa.commons.service.impl.EmpServiceImpl;
import com.dailyblue.java.project.oa.commons.util.ResultCode;
import com.dailyblue.java.project.oa.commons.util.ResultTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
public class LoginTokenFilter extends UsernamePasswordAuthenticationFilter {

    private StringRedisTemplate stringRedisTemplate;
    private AuthenticationManager authenticationManager;

    public LoginTokenFilter(AuthenticationManager authenticationManager, StringRedisTemplate stringRedisTemplate) {
        super(authenticationManager);
        this.authenticationManager = authenticationManager;
        this.stringRedisTemplate = stringRedisTemplate;
        // 关闭登录只允许 post
        this.setPostOnly(false);
        // 设置登陆路径，并且post请求
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/emp/login", "GET"));
    }

    // 用户登陆
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        log.info("用户开始登陆，账号：{}，密码：{}", username, password);
        // 传递下去，登录接口 /user/login 调用请求时触发
        // UsernamePasswordAuthenticationToken 封装登录时传递来的数据信息
        // 交给 AuthenticationManager  进行登录认证校验
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
    }

    // 登陆成功
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        // 把token信息保持到redis中
        EmpDetails empDetails = (EmpDetails) authResult.getPrincipal();
        log.info("用户登陆成功:{}", empDetails);
        Emp emp = empDetails.getEmp();
        String token = JwtConfig.getJwtToken(emp);
        stringRedisTemplate.opsForValue().set("token:" + emp.getId(), token);
        // 返回登陆成功的相关信息
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println(JSONArray.toJSONString(ResultTool.success(token)));
    }

    // 登陆失败
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println(JSONArray.toJSONString(ResultTool.fail(ResultCode.COMMON_FAIL)));
    }
}
